package squares;

import static org.junit.Assert.*;


import org.junit.Before;
import org.junit.Test;

import borders.*;

import squares.Square.TemperatureType;

public class SquareTest {

	private static  Square squareHumidity,squareTemperature1,squareColdDamage,squareNoColdDamage,squareHeatDamage,
	squareNoHeatDamage,squareRustDamage,squareNoRustDamage,squareExceptionHeatDamage,squareInhabitability1,squareInhabitability2,squareSlippery1,squareSlippery2,squareSlippery3;
	private static TransparentSquare transparentSquare1,transparentSquare2;
	@Before
	public void setUp() throws Exception {
		Square.setMinTemperature(-200, TemperatureType.CELSIUS);
		Square.setMaxTemperature(5000,TemperatureType.CELSIUS);
		squareTemperature1 = new Square(3200,TemperatureType.CELSIUS,23,false, false);
		squareColdDamage = new Square(-150,TemperatureType.CELSIUS,40.33,false, false);
		squareNoColdDamage = new Square(150,TemperatureType.CELSIUS,32,true, false);
		squareHeatDamage = new Square(150,TemperatureType.CELSIUS,32,true, false);
		squareNoHeatDamage = new Square(-150,TemperatureType.CELSIUS,32,true, false);
		squareHumidity = new Square(132,TemperatureType.FAHRENHEIT,30,false, false);
		squareRustDamage = new Square(123,TemperatureType.CELSIUS,50,false, false);
		squareNoRustDamage = new Square(234,TemperatureType.KELVIN,15,false, false);
		squareExceptionHeatDamage = new Square(1000,TemperatureType.CELSIUS,14,false, false);
		squareInhabitability1 = new Square(100,TemperatureType.CELSIUS,30,false, false);
		squareInhabitability2 = new Square(40,TemperatureType.CELSIUS,89.92,false, false);
		squareSlippery1 = new Square(2000, TemperatureType.CELSIUS,100,false, false);
		squareSlippery2 = new Square(3000, TemperatureType.CELSIUS,30,true, false);
		squareSlippery3 = new Square(2500, TemperatureType.CELSIUS,30,false, false);
		transparentSquare1 = new TransparentSquare(1500,TemperatureType.CELSIUS,50,false,false,Direction.WEST, false);
		transparentSquare2 = new TransparentSquare(1000,TemperatureType.CELSIUS,40,false,false,Direction.NORTH, false);
	
		}
	@Test
	public final void squareConstructor_legalCase() throws Exception
	{
		Square square1 = new Square(1000,TemperatureType.CELSIUS,40.42, false, false);
		Square square2 = new Square(2000,TemperatureType.KELVIN,50.23,true, false);
		assertEquals(40.42,square1.getHumidity(),0);
		assertEquals(1000,square1.getTemperature(),0);
		assertEquals(false,square1.getSlipperyFloor());
		assertEquals(50.23,square2.getHumidity(),0);
		assertEquals(2000,square2.getTemperature(TemperatureType.KELVIN),0);
		assertEquals(true,square2.getSlipperyFloor());
	}
	
	@Test
	public final void transparentSquare_changeBorder_illegalCase1()
	{
		Border border = transparentSquare2.getBorderAt(Direction.EAST);
		transparentSquare2.changeBorderAt(Direction.EAST, new Door(transparentSquare2,false));
		assertEquals(border,transparentSquare2.getBorderAt(Direction.EAST));
	}
	@Test
	public final void transparentSquare_changeBorder_illegalCase2()
	{
		Border border = transparentSquare1.getBorderAt(Direction.WEST);
		transparentSquare1.changeBorderAt(Direction.WEST, new Open(transparentSquare1));
		assertEquals(border,transparentSquare1.getBorderAt(Direction.WEST));
	}
	@Test
	public final void transparentSquare_changeBorder_legalCase1()
	{
		Border border = new Door(transparentSquare2,false);
		transparentSquare2.changeBorderAt(Direction.SOUTH, border);
		assertEquals(border,transparentSquare2.getBorderAt(Direction.SOUTH));
	}
	@Test (expected = InvalidTemperatureException.class)
	public final void squareConstructor_IllegalCase1() throws Exception
	{
		new Square(10000,TemperatureType.FAHRENHEIT,40.4, false, false);
	}
	@Test (expected = InvalidTemperatureException.class)
	public final void squareConstructor_IllegalCase2() throws Exception
	{
		new Square(-300,TemperatureType.CELSIUS,99,true, false);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void squareConstructor_IllegalCase3() throws Exception
	{
		new Square(1000,null,23.23,true, false);
	}
	@Test (expected = InvalidHumidityException.class)
	public final void squareConstructor_illegalCase4() throws Exception
	{
		new Square(300,TemperatureType.CELSIUS,211,true, false);
	}
	public final void squareConstructorStandard_legalCase()
	{
		new Square();
	}
	@Test
	public final void HasTwoDecimals_trueCase()
	{
		assertTrue(Square.hasTwoDecimals(45.89));
	}

	@Test
	public final void isValidHumidity_trueCase()
	{
		assertTrue(Square.isValidHumidity(48.32));
		
	}
	@Test
	public final void isValidHumidity_falseCase()
	{
		assertFalse(Square.isValidHumidity(123));
	}
	@Test
	public final void isValidTemperature_trueCase() throws Exception
	{
		assertTrue(Square.isValidTemperature(1000,TemperatureType.CELSIUS));
		assertTrue(Square.isValidTemperature(5000, TemperatureType.KELVIN));
		assertTrue(Square.isValidTemperature(100, TemperatureType.KELVIN));
	}
	@Test
	public final void isValidtemperature_falseCase() throws Exception
	{
		assertFalse(Square.isValidTemperature(6000,TemperatureType.CELSIUS));
		assertFalse(Square.isValidTemperature(-400,TemperatureType.FAHRENHEIT));
		assertFalse(Square.isValidTemperature(0, TemperatureType.KELVIN));
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void isValidTemperature_ExceptionCase() throws Exception
	{
		Square.isValidTemperature(0,null);
	}
	@Test (expected = AssertionError.class)
	public final void SetHumidity_illegalCase()
	{
		squareHumidity.setHumidity(-50.34);
	}
	@Test
	public final void GetTemperatureWithType_legalCase() throws Exception
	{

		assertEquals(3473.15,squareTemperature1.getTemperature(TemperatureType.KELVIN),0);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void getTemperatureWithType_exceptionCase() throws Exception
	{
		squareTemperature1.getTemperature(null);
	}
	@Test
	public final void getMinTemperatureWithType_legalCase() throws Exception
	{
		Square.setMinTemperature(-200,TemperatureType.CELSIUS);
		assertEquals(-328,Square.getMinTemperature(TemperatureType.FAHRENHEIT),0);
		assertEquals(73.15,Square.getMinTemperature(TemperatureType.KELVIN),0.01);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void getMinTemperatureWithType_exception() throws Exception
	{
		Square.getMinTemperature(null);
	}
	@Test
	public final void getMaxTemperatureWithType_legalCase() throws Exception
	{
		Square.setMaxTemperature(5000, TemperatureType.CELSIUS);
		assertEquals(5000,Square.getMaxTemperature(),0);
		assertEquals(5000*1.8+32,Square.getMaxTemperature(TemperatureType.FAHRENHEIT),0);
		assertEquals(5000+273.15,Square.getMaxTemperature(TemperatureType.KELVIN),0);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void getMaxTemperatureWithType_exception() throws Exception
	{
		Square.getMaxTemperature(null);
	}
	@Test
	public final void setMinTemperature_legalCase() throws Exception
	{
		Square.setMinTemperature(-200, TemperatureType.KELVIN);
		assertEquals(-200,Square.getMinTemperature(TemperatureType.KELVIN),0);
		Square.setMinTemperature(-200, TemperatureType.CELSIUS);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setMinTemperature_illegalCase1() throws Exception
	{
		Square.setMinTemperature(Square.getMaxTemperature() + 1, TemperatureType.CELSIUS);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void setMinTemperature_illegalCase2() throws Exception
	{
		Square.setMinTemperature(-2000,null);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setMinTemperature_illegalCase3() throws Exception
	{
		Square.setMinTemperature(-Double.MAX_VALUE + 1, TemperatureType.CELSIUS);
	}
	@Test
	public final void setMaxTemperature_legalCase() throws Exception
	{
		Square.setMaxTemperature(6000, TemperatureType.KELVIN);
		assertEquals(6000,Square.getMaxTemperature(TemperatureType.KELVIN),0);
		Square.setMaxTemperature(5000, TemperatureType.CELSIUS);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setMaxTemperature_illegalCase1() throws Exception
	{
		Square.setMaxTemperature(Square.getMinTemperature() - 1, TemperatureType.CELSIUS);
		Square.setMaxTemperature(5000, TemperatureType.CELSIUS);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void setMaxTemperature_illegalCase2() throws Exception
	{
		Square.setMaxTemperature(2000,null);
		Square.setMaxTemperature(5000, TemperatureType.CELSIUS);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setMaxTemperature_illegalCase3() throws Exception
	{
		Square.setMaxTemperature(Double.MAX_VALUE - 1, TemperatureType.CELSIUS);
	}
	@Test
	public final void IsValidMinTemperature_trueCases() throws Exception
	{
		assertTrue(Square.isValidMinTemperature(Square.getMaxTemperature() -1, TemperatureType.CELSIUS));
		assertTrue(Square.isValidMinTemperature(Square.getMinTemperature(TemperatureType.KELVIN) - 10, TemperatureType.KELVIN));
	}
	@Test
	public final void isValidMinTemperature_falseCases() throws Exception
	{
		assertFalse(Square.isValidMinTemperature(-Double.MAX_VALUE + 5, TemperatureType.CELSIUS));
		assertFalse(Square.isValidMinTemperature((-Double.MAX_VALUE + 250),TemperatureType.KELVIN));
	}
	@Test
	public final void isValidMaxTemperature_trueCases() throws Exception
	{
		assertTrue(Square.isValidMaxTemperature(Square.getMaxTemperature() +1, TemperatureType.CELSIUS));
		assertTrue(Square.isValidMaxTemperature(Square.getMaxTemperature(TemperatureType.KELVIN) + 10, TemperatureType.KELVIN));
	}
	@Test
	public final void isValidMaxTemperature_falseCases() throws Exception
	{
		assertFalse(Square.isValidMaxTemperature(Double.MAX_VALUE - 5, TemperatureType.CELSIUS));
		assertFalse(Square.isValidMaxTemperature((Double.MAX_VALUE- 15),TemperatureType.KELVIN));
		assertTrue(Square.isValidMaxTemperature((Double.MAX_VALUE/1.8) + 1, TemperatureType.CELSIUS));// onverklaarbaar juist
	}
	@Test
	public final void ColdDamage_damageCase()
	{
		assertEquals(14,squareColdDamage.coldDamage());
	}
	@Test
	public final void ColdDamage_NoDamageCase()
	{
		assertEquals(0,squareNoColdDamage.coldDamage());
	}
	@Test
	public final void HeatDamage_damageCase() throws Exception
	{
		assertEquals(7,squareHeatDamage.heatDamage());
	}
	@Test
	public final void HeatDamage_NoDamageCase() throws Exception
	{
		assertEquals(0,squareNoHeatDamage.heatDamage());
	}
	@Test (expected = IllegalArgumentException.class)
	public final void HeatDamage_ExceptionCase() throws Exception
	{
		Square.setTemperatureStepHeatDamage(0.01);
		Square.setMaxTemperature(Double.MAX_VALUE/1.8 -10000, TemperatureType.CELSIUS);
		squareExceptionHeatDamage.setTemperature(Double.MAX_VALUE/1.8 - 20000);
		squareExceptionHeatDamage.heatDamage();
		Square.setTemperatureStepHeatDamage(15);
		Square.setMaxTemperature(5000,TemperatureType.CELSIUS);
	}
	@Test
	public final void TemperatureHighEnoughForHeatDamage_trueCase()
	{
		assertTrue(squareHeatDamage.temperatureHighEnoughForHeatDamage());
	}
	@Test
	public final void TemperatureHighEnoughForHeatDamage_falseCase()
	{
		assertFalse(squareNoHeatDamage.temperatureHighEnoughForHeatDamage());
	}
	@Test
	public final void TemperatureLowEnoughForColdDamage_trueCase()
	{
		assertTrue(squareColdDamage.temperatureLowEnoughForColdDamage());
	}
	@Test
	public final void TemperatureLowEnoughForColdDamage_falseCase()
	{
		assertFalse(squareNoColdDamage.temperatureLowEnoughForColdDamage());
	}
	@Test
	public final void RustDamage_damageCase()
	{
		assertEquals(2,squareRustDamage.RustDamage());
	}
	@Test
	public final void RustDamage_noDamageCase()
	{
		assertEquals(0,squareNoRustDamage.RustDamage());
	}
	@Test
	public final void RustPossible_trueCase()
	{
		assertTrue(squareRustDamage.rustPossible());
	}
	@Test
	public final void RustPossible_falseCase()
	{
		assertFalse(squareNoRustDamage.rustPossible());
	}
	@Test
	public final void Inhabitability() throws Exception
	{
		Square.setTemperatureStepHeatDamage(15);
		Square.setStartTemperatureHeatDamage(35, TemperatureType.CELSIUS);
		assertEquals(-0.949,squareInhabitability1.inhabitability(),0.001);
		assertEquals(0,squareInhabitability2.inhabitability(),0);
	}
	@Test
	public final void setStartTemperatureHeatDamage_legalCase() throws Exception
	{
		Square.setStartTemperatureHeatDamage(200,TemperatureType.CELSIUS);
	}
	@Test
	public final void setTemperatureStepHeatDamage_legalCase() throws Exception
	{
		Square.setTemperatureStepHeatDamage(123);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureStepHeatDamage_IllegalCase() throws Exception
	{
		Square.setTemperatureStepHeatDamage(-1);
	}
	@Test
	public final void Slippery_trueCase() throws Exception
	{
		assertTrue(squareSlippery1.slippery());
		squareSlippery1.setHumidity(50);
		squareSlippery1.setTemperature(-15);
		assertTrue(squareSlippery1.slippery());
		assertTrue(squareSlippery2.slippery());
	}
	@Test
	public final void Slippery_falseCase() throws Exception
	{
		assertFalse(squareSlippery3.slippery());
	}
	@Test
	public final void setTemperatureToCelsius_legalCase() throws Exception
	{
		squareTemperature1.setTemperatureToCelsius(TemperatureType.FAHRENHEIT, 4000);
		assertEquals(2204.44,squareTemperature1.getTemperature(),0.01);
	}
	@Test (expected = InvalidTemperatureException.class)
	public final void setTemperatureToCelsius_exceptionCase1() throws Exception
	{
		squareTemperature1.setTemperatureToCelsius(TemperatureType.FAHRENHEIT,10000);
	}
	@Test (expected = IllegalTemperatureTypeException.class)
	public final void setTemperatureToCelsius_exceptionCase2() throws Exception
	{
		squareTemperature1.setTemperatureToCelsius(null, 10);
	}
	@Test
	public final void setTemperatureMergeConstant_legalCase()
	{
		Square.setTemperatureMergeConstant(0.3);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureMergeConstant_illegalCase()
	{
		Square.setTemperatureMergeConstant(213);
	}
	@Test
	public final void getTemperatureInCelsius_legalCase() throws Exception
	{
		assertEquals(1093.33,Square.getTemperatureInCelsius(2000, TemperatureType.FAHRENHEIT),0.01);
	}
	
}
